package com.flyco.modules.stm.controller;

import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.flyco.common.constant.StockConstant;
import com.flyco.modules.pms.entity.PmsProduct;
import com.flyco.modules.pms.service.IPmsProductService;
import com.flyco.modules.stm.entity.*;
import com.flyco.modules.stm.model.StmConvertItemModel;
import com.flyco.modules.stm.service.IStmStockService;
import com.flyco.modules.stm.service.IStmStoreInfoService;
import com.flyco.modules.stm.vo.StmStockVO;
import org.apache.shiro.SecurityUtils;
import com.flyco.poi.excel.ExcelImportUtil;
import com.flyco.poi.excel.def.NormalExcelConstants;
import com.flyco.poi.excel.entity.ExportParams;
import com.flyco.poi.excel.entity.ImportParams;
import com.flyco.poi.excel.view.EntityExcelView;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.query.QueryGenerator;
import com.flyco.common.util.oConvertUtils;
import com.flyco.modules.stm.vo.StmConvertPage;
import com.flyco.modules.stm.service.IStmConvertService;
import com.flyco.modules.stm.service.IStmConvertItemService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.flyco.common.aspect.annotation.AutoLog;

/**
 * @Description: 门店转换单表
 * @Author: flyco
 * @Date: 2021-01-19
 * @Version: V1.0
 */
@Api(tags = "门店转换单表")
@RestController
@RequestMapping("/f/stm/stmConvert")
@Slf4j
public class StmConvertController {
    @Autowired
    private IStmConvertService stmConvertService;
    @Autowired
    private IStmConvertItemService stmConvertItemService;
    @Autowired
    private IStmStoreInfoService stmStoreInfoService;
    @Autowired
    private IPmsProductService pmsProductService;
    @Autowired
    private IStmStockService stmStockService;

    /**
     * 分页列表查询
     *
     * @param stmConvert
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "门店转换单表-分页列表查询")
    @ApiOperation(value = "门店转换单表-分页列表查询", notes = "门店转换单表-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(StmConvert stmConvert,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<StmConvert> queryWrapper = QueryGenerator.initQueryWrapper(stmConvert, req.getParameterMap());
        Page<StmConvert> page = new Page<StmConvert>(pageNo, pageSize);
        IPage<StmConvert> pageList = stmConvertService.page(page, queryWrapper);
        if (pageList.getTotal() > 0) {
            List<StmStoreInfo> storeInfos = stmStoreInfoService.list();
            Map<Long, String> storeInfoMaps = storeInfos.stream().collect(Collectors.toMap(StmStoreInfo::getStoreId, StmStoreInfo::getName, (key1, key2) -> key2));
            pageList.getRecords().forEach(convert -> {
                if (oConvertUtils.isNotEmpty(convert.getStoreId())) {
                    if (storeInfoMaps.containsKey(convert.getStoreId())) {
                        convert.setStoreId_dictText(storeInfoMaps.get(convert.getStoreId()));
                    } else {
                        if (Objects.equals(0L , convert.getStoreId() )) {
                            convert.setStoreId_dictText("线上商城");
                        }
                    }
                }
            });
        }
        return Result.ok(pageList);
    }

    /**
     * 添加
     *
     * @param stmConvertPage
     * @return
     */
    @AutoLog(value = "门店转换单表-添加")
    @ApiOperation(value = "门店转换单表-添加", notes = "门店转换单表-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody StmConvertPage stmConvertPage) {
        StmConvert stmConvert = new StmConvert();
        BeanUtils.copyProperties(stmConvertPage, stmConvert);
        stmConvert.setStatus(0);
        stmConvertService.save(stmConvert);
        return Result.ok("添加成功！");
    }

    /**
     * 编辑
     *
     * @param stmConvertPage
     * @return
     */
    @AutoLog(value = "门店转换单表-编辑")
    @ApiOperation(value = "门店转换单表-编辑", notes = "门店转换单表-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody StmConvertPage stmConvertPage) {
        StmConvert stmConvert = new StmConvert();
        BeanUtils.copyProperties(stmConvertPage, stmConvert);
        stmConvertService.updateById(stmConvert);
        return Result.ok("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店转换单表-通过id删除")
    @ApiOperation(value = "门店转换单表-通过id删除", notes = "门店转换单表-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) Long id) {
        stmConvertService.delMain(id);
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店转换单表-批量删除")
    @ApiOperation(value = "门店转换单表-批量删除", notes = "门店转换单表-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.stmConvertService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店转换单表-通过id查询")
    @ApiOperation(value = "门店转换单表-通过id查询", notes = "门店转换单表-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) Long id) {
        StmConvert stmConvert = stmConvertService.getById(id);
        return Result.ok(stmConvert);
    }


    /**
     * 转换
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店转换单-转换")
    @PostMapping(value = "/convert")
    public Result<?> convert(@RequestBody String[] ids) {
        LambdaQueryWrapper<StmConvert> query = new LambdaQueryWrapper<>();
        query.in(StmConvert::getId,ids);
        List<StmConvert> converts = stmConvertService.list(query);

        LambdaQueryWrapper<StmConvertItem> itemQuery = new LambdaQueryWrapper<>();
        itemQuery.in(StmConvertItem::getConvertId,ids);
        List<StmConvertItem> convertItems = stmConvertItemService.list(itemQuery);
        Map<Long, List<StmConvertItem>> itemMap = convertItems.stream().collect(Collectors.groupingBy(e -> e.getConvertId()));

        converts.forEach(convert -> {
            if(Arrays.asList(0,1,3).contains(convert.getStatus())){
                if (itemMap.containsKey(convert.getId())) {
                    List<StmConvertItem> items = itemMap.get(convert.getId());
                    List<StmStockVO> outStockVOList = new ArrayList<>();
                    List<StmStockVO> inStockVOList = new ArrayList<>();
                    items.forEach(item->{
                        StmStockVO vo = BeanUtils.instantiateClass(StmStockVO.class);
                        vo.setProductId(item.getProductId());
                        vo.setProductSn(item.getProductSn());
                        vo.setStockType(item.getStockType());
                        vo.setProductQty(item.getProductQty());
                        if (Objects.equals("CONVERT_FROM", item.getFromToFlag())) {
                            outStockVOList.add(vo);
                        } else {
                            inStockVOList.add(vo);
                        }
                    });
                    String changeReason = "转换出库";
                    if (outStockVOList.size() > 0) {
                        stmStockService.stockInOut(outStockVOList, convert.getStoreId(), StockConstant.STOCK_OUT, StockConstant.STOCK_OUT_TYPE_CONVERT, StockConstant.RECEIPT_TYPE_CONVERT, convert.getId().toString(), changeReason );
                    }
                    changeReason = "转换入库";
                    if (inStockVOList.size() > 0) {
                        stmStockService.stockInOut(inStockVOList, convert.getStoreId(), StockConstant.STOCK_IN, StockConstant.STOCK_IN_TYPE_CONVERT, StockConstant.RECEIPT_TYPE_CONVERT, convert.getId().toString(), changeReason );
                    }
                    StmConvert updateConvert = new StmConvert();
                    updateConvert.setStatus(5);
                    updateConvert.setId(convert.getId());
                    stmConvertService.updateById(updateConvert);
                }
            }
        });
        return Result.ok("转换成功！");
    }

    //===========================以下是子表信息操作相关API====================================

    /**
     * 通过主表id查询门店转换单明细表
     *
     * @param stmConvertItem
     * @return
     */
    @AutoLog(value = "门店转换单明细表-通过主表id查询")
    @ApiOperation(value = "门店转换单明细表-通过主表id查询", notes = "门店转换单明细表-通过主表id查询")
    @GetMapping(value = "/listStmConvertItemByMainId")
    public Result<?> listStmConvertItemByMainId(StmConvertItem stmConvertItem,
                                                @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                HttpServletRequest req) {
        if (stmConvertItem.getConvertId() != null) {
            QueryWrapper<StmConvertItem> queryWrapper = QueryGenerator.initQueryWrapper(stmConvertItem, req.getParameterMap());
            Page<StmConvertItem> page = new Page<StmConvertItem>(pageNo, pageSize);
            IPage<StmConvertItem> pageList = stmConvertItemService.page(page, queryWrapper);
            return Result.ok(pageList);
        } else {
			return Result.error("请选择一条记录");
        }
    }

    /**
     * 添加门店转换单明细表
     *
     * @param stmConvertItemModel
     * @return
     */
    @AutoLog(value = "门店转换单明细表-添加")
    @ApiOperation(value = "门店转换单明细表-添加", notes = "门店转换单明细表-添加")
    @PostMapping(value = "/addStmConvertItem")
    public Result<?> addStmConvertItem(@RequestBody StmConvertItemModel stmConvertItemModel) {
        if (oConvertUtils.isEmpty(stmConvertItemModel) || oConvertUtils.isEmpty(stmConvertItemModel.getConvertId()) || oConvertUtils.isEmpty(stmConvertItemModel.getDetailList())) {
            return Result.error("数据为空！");
        }
        StmConvert stmConvert = stmConvertService.getById(stmConvertItemModel.getConvertId());
        if (oConvertUtils.isEmpty(stmConvert)) {
            return Result.error("转换单主表记录为空，请检查后重试！");
        }
        if (stmConvert.getStatus() > 0) {
            return Result.error("该转换单不是初始状态，不可再增加商品！");
        }
        List<String> productSns = stmConvertItemModel.getDetailList().stream().map(StmConvertItem::getProductSn).collect(Collectors.toList());
        long count = productSns.stream().distinct().count();
        if (count < productSns.size()) {
            return Result.error("新添加的记录中存在重复数据，请重核对后重试！");
        }
        LambdaQueryWrapper<PmsProduct> query = new LambdaQueryWrapper<>();
        query.in(PmsProduct::getProductSn, productSns);
        List<PmsProduct> products = pmsProductService.list(query);
        Map<String, Long> productMaps = products.stream().collect(Collectors.toMap(PmsProduct::getProductSn, PmsProduct::getId, (key1, key2) -> key2));
        List<StmConvertItem> stmConvertItemList = stmConvertItemService.selectByMainId(stmConvertItemModel.getConvertId());
        if (oConvertUtils.isNotEmpty(stmConvertItemList) && stmConvertItemList.size() > 0) {
            List<Long> productIds = products.stream().map(PmsProduct::getId).collect(Collectors.toList());
            List<Long> dbItemProductIds = stmConvertItemList.stream().map(StmConvertItem::getProductId).collect(Collectors.toList());
            List<Long> mixes = productIds.stream().filter(r -> dbItemProductIds.contains(r)).collect(Collectors.toList());
            if (oConvertUtils.isNotEmpty(mixes) && mixes.size() > 0) {
                return Result.error("新添加的记录已存在，请重核对后重试！");
            }
        }
        stmConvertItemModel.getDetailList().forEach(r -> {
            r.setConvertId(stmConvertItemModel.getConvertId());
            r.setProductId(productMaps.get(r.getProductSn()));
        });
        stmConvertItemService.saveBatch(stmConvertItemModel.getDetailList());
        return Result.ok("添加门店转换单明细表成功！");
    }

    /**
     * 编辑门店转换单明细表
     *
     * @param stmConvertItem
     * @return
     */
    @AutoLog(value = "门店转换单明细表-编辑")
    @ApiOperation(value = "门店转换单明细表-编辑", notes = "门店转换单明细表-编辑")
    @PutMapping("/editStmConvertItem")
    public Result<?> editStmConvertItem(@RequestBody StmConvertItem stmConvertItem) {
        StmConvert stmConvert = stmConvertService.getById(stmConvertItem.getConvertId());
        if (oConvertUtils.isEmpty(stmConvert)) {
            return Result.error("转换单主表记录为空，请检查后重试！");
        }
        if (stmConvert.getStatus() > 0) {
            return Result.error("该转换单不是初始状态，不可编辑商品！");
        }
        stmConvertItemService.updateById(stmConvertItem);
        return Result.ok("编辑门店转换单明细表成功！");
    }

    /**
     * 通过id删除门店转换单明细表
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店转换单明细表-通过id删除")
    @ApiOperation(value = "门店转换单明细表-通过id删除", notes = "门店转换单明细表-通过id删除")
    @DeleteMapping(value = "/deleteStmConvertItem")
    public Result<?> deleteStmConvertItem(@RequestParam(name = "id", required = true) String id) {
        StmConvertItem stmConvertItem = stmConvertItemService.getById(id);
        StmConvert stmConvert = stmConvertService.getById(stmConvertItem.getConvertId());
        if (oConvertUtils.isEmpty(stmConvert)) {
            return Result.error("转换单主表记录为空，请检查后重试！");
        }
        if (stmConvert.getStatus() > 0) {
            return Result.error("该转换单不是初始状态，不可删除商品！");
        }
        stmConvertItemService.removeById(id);
        return Result.ok("删除门店转换单明细表成功！");
    }

    /**
     * 批量删除门店转换单明细表
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店转换单明细表-批量删除")
    @ApiOperation(value = "门店转换单明细表-批量删除", notes = "门店转换单明细表-批量删除")
    @DeleteMapping(value = "/deleteBatchStmConvertItem")
    public Result<?> deleteBatchStmConvertItem(@RequestParam(name = "ids", required = true) String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不识别！");
        }
        this.stmConvertItemService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");

    }


    /**
     * 导出excel
     *
     * @param request
     * @param stmConvert
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, StmConvert stmConvert) {
        // Step.1 组装查询条件
        QueryWrapper<StmConvert> queryWrapper = QueryGenerator.initQueryWrapper(stmConvert, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<StmConvertPage> pageList = new ArrayList<StmConvertPage>();
        List<StmConvert> stmConvertList = stmConvertService.list(queryWrapper);
        for (StmConvert temp : stmConvertList) {
            StmConvertPage vo = new StmConvertPage();
            BeanUtils.copyProperties(temp, vo);
            List<StmConvertItem> stmConvertItemList = stmConvertItemService.selectByMainId(temp.getId());
            vo.setStmConvertItemList(stmConvertItemList);
            pageList.add(vo);
        }
        //Step.3 调用AutoPoi导出Excel
        ModelAndView mv = new ModelAndView(new EntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "门店转换单表");
        mv.addObject(NormalExcelConstants.CLASS, StmConvertPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("门店转换单表数据", "导出人:" + sysUser.getRealname(), "门店转换单表"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<StmConvertPage> list = ExcelImportUtil.importExcel(file.getInputStream(), StmConvertPage.class, params);
                for (StmConvertPage page : list) {
                    StmConvert po = new StmConvert();
                    BeanUtils.copyProperties(page, po);
                    stmConvertService.saveMain(po, page.getStmConvertItemList());
                }
                return Result.ok("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.ok("文件导入失败！");
    }
}
